﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Shell.KnowledgeBase
{
    public class BindingContext
    {
        private readonly Dictionary<Variable, Term> _binding;

        public BindingContext()
        {
            _binding = new Dictionary<Variable, Term>();
        }

        public BindingContext(BindingContext chainedContext)
        {
            _binding = new Dictionary<Variable, Term>(chainedContext._binding);
        }

        public BindingContext Derive()
        {
            return new BindingContext(this);
        }

        public void Bind(Variable variable, Term term)
        {
            if (variable == term)
            {
                return;
            }

            if (_binding.ContainsKey(variable) && _binding[variable] == term)
            {
                return;
            }

            _binding.Add(variable, term);
        }

        public Term ResolveTerm(Term term)
        {
            return IsBoundVariable(term)
                       ? ResolveTerm(_binding[(Variable) term])
                       : term;
        }

        public override string ToString()
        {
            return string.Join(
                " ,",
                _binding.Select(_ => string.Format("{0} = {1}", _.Key, _.Value)));
        }

        public bool IsBoundVariable(Term term)
        {
            return (term is Variable) && _binding.ContainsKey((Variable) term);
        }

        public bool IsFreeVariable(Term term)
        {
            return (term is Variable) && !_binding.ContainsKey((Variable) term);
        }
    }
}